package com.fary.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.fary.constant.SchedulerConstant;
import com.fary.po.CornTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.Task;
import org.springframework.scheduling.config.TriggerTask;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

import static com.fary.util.TaskBean.cornTaskMapper;
import static com.fary.util.TaskBean.executeTaskService;

/**
 * 动态定时任务（从数据库获取配置）——多个任务
 **/
@Slf4j
@Component
public class DynamicSchedulingConfigurer implements SchedulingConfigurer {

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    /**
     * 正在执行的任务
     */
    private List<CornTask> initCronList;

    private ScheduledTaskRegistrar taskRegistrar;

    private Set<ScheduledTask> scheduledTasks;

    private final Map<String, Task> triggerTaskMap = new HashMap<>();


    @SuppressWarnings("unchecked")
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        this.taskRegistrar = scheduledTaskRegistrar;
        // 获取任务列表
        scheduledTasks = (Set<ScheduledTask>) ReflectUtil.getFieldValue(taskRegistrar, "scheduledTasks");

        //1: 用自定义的线程池
        scheduledTaskRegistrar.setScheduler(threadPoolTaskScheduler);

        //2.获取需要执行的所有的任务
        initCronList = cornTaskMapper.getAllEnableCornsList();

        //3.根据配置情况执行对应的任务
        for (CornTask cornTask : initCronList) {
            TriggerTask triggerTask = customizeTriggerTask(cornTask);
            triggerTaskMap.put(cornTask.getCornid(), triggerTask);
            scheduledTaskRegistrar.addTriggerTask(triggerTask);
        }

    }

    public TriggerTask customizeTriggerTask(CornTask cornTask) {
        return new TriggerTask(() -> executeTask(cornTask), triggerContext -> {
            CronTrigger trigger = new CronTrigger(cornTask.getCorn());
            return trigger.nextExecutionTime(triggerContext);
        });
    }

    /**
     * 在这里处理所有的业务
     */
    public void executeTask(CornTask cornEntity) {
        if (!"T".equals(cornEntity.getEnable())) {
            return;
        }
        // 动态刷新定时任务
        if (SchedulerConstant.RefreshTask.equals(cornEntity.getCornid())) {
            Map<String, CornTask> initCornTaskMap = initCronList.stream().collect(Collectors.toMap(CornTask::getCornid, cornTask -> cornTask));
            List<CornTask> newCronTaskList = cornTaskMapper.getAllCornsList();
            Map<String, CornTask> newCornTaskMap = newCronTaskList.stream().collect(Collectors.toMap(CornTask::getCornid, cornTask -> cornTask));
            Collection<String> cornIds = CollectionUtil.union(initCornTaskMap.keySet(), newCornTaskMap.keySet());
            for (String cornId : cornIds) {
                CornTask cornTask = initCornTaskMap.get(cornId);
                CornTask newCornTask = newCornTaskMap.get(cornId);
                if (newCornTask != null && "T".equals(newCornTask.getEnable())) {
                    if (cornTask == null) {
                        // 新增定时任务配置
                        initCronList.add(newCornTask);
                        addTriggerTask(newCornTask.getCornid(), customizeTriggerTask(newCornTask));
                    } else if (!StrUtil.equals(cornTask.getCorn(), newCornTask.getCorn())) {
                        // 修改定时任务配置
                        cornTask.setCorn(newCornTask.getCorn());
                        resetTriggerTask(cornTask.getCornid(), customizeTriggerTask(cornTask));
                    }
                } else if (cornTask != null) {
                    // 删除定时任务配置
                    initCronList.remove(cornTask);
                    cancelTriggerTask(cornTask.getCornid());
                }
            }
        } else {
            System.out.println(DateUtil.now() + " 任务ID--->" + cornEntity.getCornid() + " 任务Corn--->" + cornEntity.getCorn() + "-->" + Thread.currentThread().getName());
            executeTaskService.doExecuteTask(cornEntity.getCornid());
        }
    }



    /**
     * 添加任务
     */
    public void addTriggerTask(String taskId, TriggerTask triggerTask) {
        if (triggerTaskMap.containsKey(taskId)) {
            throw new SchedulingException("the taskId[" + taskId + "] was added.");
        }
        triggerTaskMap.put(taskId, triggerTask);
        taskRegistrar.addTriggerTask(triggerTask);
        scheduledTasks.add(taskRegistrar.scheduleTriggerTask(triggerTask));
    }

    /**
     * 取消任务
     */
    public void cancelTriggerTask(String taskId) {
        for (ScheduledTask scheduledTask : scheduledTasks) {
            if (scheduledTask != null && scheduledTask.getTask().equals(triggerTaskMap.get(taskId))) {
                scheduledTask.cancel();
                scheduledTasks.remove(scheduledTask);
                break;
            }
        }
        triggerTaskMap.remove(taskId);
    }

    /**
     * 重置任务
     */
    public void resetTriggerTask(String taskId, TriggerTask triggerTask) {
        cancelTriggerTask(taskId);
        addTriggerTask(taskId, triggerTask);
    }
}
